home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / intuisup.lha / Intuisup / source.lha / Gadgets / gadgets1.c < prev    next >
C/C++ Source or Header  |  1992-10-21  |  55KB  |  1,971 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1991 by Torsten Jürgeleit
  4.  *
  5.  *    Name .....: gadgets1.c
  6.  *    Created ..: Thursday 19-Dec-91 20:52:50
  7.  *    Revision .: 21
  8.  *
  9.  *    Date        Author                 Comment
  10.  *    =========   ====================   ====================
  11.  *    21-Oct-92   Torsten Jürgeleit      corrected autorepeat of arrow
  12.  *                       gadgets under Kick 2.x too
  13.  *    14-Sep-92   Torsten Jürgeleit      now set_gadget_attributes() with
  14.  *                       data1-3 set to USE_CURRENT_VALUE
  15.  *                       returns current setting
  16.  *    12-Sep-92   Torsten Jürgeleit      forgot to copy original IntuiMessage
  17.  *                       into ISUP IntuiMessage
  18.  *    10-Aug-92   Torsten Jürgeleit      perform_gadget_action(): don't use
  19.  *                       lv_SelectedEntry anymore
  20.  *    23-Jul-92   Torsten Jürgeleit      perform_gadget_action(): report too
  21.  *                       if same palette color entry selected
  22.  *                       again
  23.  *    23-Jul-92   Torsten Jürgeleit      perform_gadget_action(): only use
  24.  *                       lv_SelectedEntry if GADGET_DATA_-
  25.  *                       FLAG_LISTVIEW_SHOW_SELECTED set
  26.  *    20-Jul-92   Torsten Jürgeleit      mark end of chained gadgets in
  27.  *                       display_gadgets()
  28.  *    19-Jul-92   Torsten Jürgeleit      corrected replying of IntuiMessages
  29.  *                       in remove_gadgets()
  30.  *    19-Jul-92   Torsten Jürgeleit      remove/display_visible_gadget_lists()
  31.  *                       imported from requester/requester.c
  32.  *    16-Jul-92   Torsten Jürgeleit      size of count gadget changeable
  33.  *                       via modify_gadgets()
  34.  *    16-Jul-92   Torsten Jürgeleit      lower and upper bound of count
  35.  *                       gadget now changeable via
  36.  *                       set_gadget_attributes()
  37.  *    11-Jul-92   Torsten Jürgeleit      now RAWKEY instead of VANILLAKEY
  38.  *                                         used for gadget hotkeys
  39.  *    14-Apr-92   Torsten Jürgeleit      if flag GADGET_DATA_FLAG_NO_CLEAR
  40.  *                                         set then don't clear area occupied
  41.  *                                         by ISUP object before drawing
  42.  *    30-Apr-92   Torsten Jürgeleit      area gadget occupies now cleared 
  43.  *                                         before diplaying it
  44.  *    28-Apr-92   Torsten Jürgeleit      correct disabling in
  45.  *                                         set_gadget_attributes() if gadgets
  46.  *                                         not displayed -> gl_Window was not
  47.  *                                         defined
  48.  *    20-Apr-92   Torsten Jürgeleit      disable refresh if same entry
  49.  *                                         from list view selected
  50.  *    01-Apr-92   Torsten Jürgeleit      any references to gadget data
  51.  *                                         via gl_Data removed
  52.  *    01-Apr-92   Torsten Jürgeleit      changed parameter size of
  53.  *                                         modify_gadget() for new value of
  54.  *                                         USE_CURRENT_VALUE (1L << 31)
  55.  *    11-Mar-92   Torsten Jürgeleit      guru if toggeling DISABLED of NOT
  56.  *                                         displayed ISUP object via
  57.  *                                         set_gadget_attributes()
  58.  *    24-Jan-92   Torsten Jürgeleit      new function modify_gadget()
  59.  *    28-Dec-91   Torsten Jürgeleit      correct highliting of toggle
  60.  *                                         select buttons
  61.  *    19-Dec-91   Torsten Jürgeleit      Created this file!
  62.  *
  63.  ****************************************************************************
  64.  *
  65.  *    Gadget support routines - part 1
  66.  *
  67.  * $Revision Header ********************************************************/
  68.  
  69.     /* Includes */
  70.  
  71. #include <exec/types.h>
  72. #include <exec/memory.h>
  73. #include <devices/inputevent.h>
  74. #include <intuition/intuition.h>
  75. #ifdef AZTEC_C
  76. #include <functions.h>   /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
  77. #endif
  78. #include <libraries/memwatch.h>   /* header file for memory debug link library (Fish 240) - AFTER functions.h */
  79. #include <string.h>
  80. #include "/render/render.h"
  81. #include "/borders/borders.h"
  82. #include "/texts/texts.h"
  83. #include "/language/language.h"
  84. #include "/pointer/pointer.h"
  85. #include "gadgets.h"
  86. #include "imports.h"
  87.  
  88.     /* Defines */
  89.  
  90. #define CONVERT_BUFFER_SIZE    10L
  91.  
  92.     /* Imports */
  93.  
  94. IMPORT struct IntuitionBase  *IntuitionBase;
  95.  
  96.     /* Static data */
  97.  
  98. STATIC struct VisibleGadgetLists  visible_gadget_lists = {
  99.    {   /* struct SignalSemaphore  vg_Semaphore */
  100.       {   /* struct Node  ss_Link */
  101.      NULL, NULL, NT_SEMAPHORE, 0, NULL
  102.       }, 0,
  103.       {   /* struct MinList  ss_WaitQueue */
  104.      (struct MinNode *)&visible_gadget_lists.vg_Semaphore.ss_WaitQueue.mlh_Tail,
  105.      NULL,
  106.      (struct MinNode *)&visible_gadget_lists.vg_Semaphore.ss_WaitQueue.mlh_Head
  107.       },
  108.       {   /* struct SemaphoreRequest  ss_MultipleLink */
  109.      {   /* struct MinNode  sr_Link */
  110.         NULL, NULL
  111.      }, NULL
  112.       }, NULL, -1
  113.    },
  114.    {   /* struct MinList  vg_MinList */
  115.       (struct MinNode *)&visible_gadget_lists.vg_MinList.mlh_Tail,
  116.       NULL,
  117.       (struct MinNode *)&visible_gadget_lists.vg_MinList.mlh_Head
  118.    }, 0
  119. };
  120. BYTE hotkey_id[] = "_";
  121.  
  122.     /* Create gadget list */
  123.  
  124.    struct GadgetList *
  125. create_gadgets(struct RenderInfo  *ri, struct GadgetData  *gd,
  126.            SHORT hoffset, SHORT voffset, BYTE **language_text_array)
  127. {
  128.    USHORT data_entries;
  129.  
  130.    if (ri && ri->ri_ID == ISUP_ID && gd &&
  131.                (data_entries = count_gadget_data_entries(gd))) {
  132.       struct GadgetList  *gl;
  133.       ULONG gl_size = sizeof(struct GadgetList) + (data_entries - 1) *
  134.                         sizeof(struct ExtendedGadget *);
  135.       if (gl = AllocMem(gl_size, (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
  136.      BYTE  *gadget_buffer;
  137.      ULONG gadget_buffer_size;
  138.  
  139.      gl->gl_RenderInfo        = ri;
  140.      gl->gl_DataEntries       = data_entries;
  141.      gl->gl_LanguageTextArray = language_text_array;
  142.      if ((gadget_buffer_size = get_gadget_buffer_size(gl, gd)) &&
  143.                    (gadget_buffer = AllocMem(gadget_buffer_size,
  144.                      (LONG)MEMF_PUBLIC | MEMF_CLEAR))) {
  145.         BYTE  *image_buffer = NULL;
  146.         ULONG image_buffer_size;
  147.  
  148.         if (image_buffer_size = get_image_buffer_size(gl, gd)) {
  149.            image_buffer = AllocMem(image_buffer_size,
  150.                          (LONG)MEMF_PUBLIC | MEMF_CHIP);
  151.         }
  152.         if (!image_buffer_size || image_buffer) {
  153.  
  154.            /* Init gadget list struct */
  155.            gl->gl_GadgetBuffer     = gadget_buffer;
  156.            gl->gl_GadgetBufferSize = gadget_buffer_size;
  157.            gl->gl_ImageBuffer      = image_buffer;
  158.            gl->gl_ImageBufferSize  = image_buffer_size;
  159.            gl->gl_ID               = ISUP_ID;
  160.            init_gadgets(gl, gd, hoffset, voffset);
  161.            return(gl);
  162.         }
  163.         FreeMem(gadget_buffer, gadget_buffer_size);
  164.      }
  165.      FreeMem(gl, gl_size);
  166.       }
  167.    }
  168.    return(NULL);
  169. }
  170.     /* Free gadget list */
  171.  
  172.    VOID
  173. free_gadgets(struct GadgetList  *gl)
  174. {
  175.    if (gl && gl->gl_ID == ISUP_ID) {
  176.       USHORT i, data_entries = gl->gl_DataEntries;
  177.  
  178.       if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  179.      remove_gadgets(gl);
  180.       }
  181.  
  182.       /* Close fonts */
  183.       for (i = 0; i < data_entries; i++) {
  184.      struct ExtendedGadget  *egad = gl->gl_Gadgets[i];
  185.  
  186.      if (egad->eg_Flags & EXTENDED_GADGET_FLAG_CLOSE_FONT) {
  187.         CloseFont(egad->eg_TextFont);
  188.      }
  189.       }
  190.  
  191.       /* Free buffers */
  192.       FreeMem(gl->gl_GadgetBuffer, gl->gl_GadgetBufferSize);
  193.       if (gl->gl_ImageBufferSize) {
  194.      FreeMem(gl->gl_ImageBuffer, gl->gl_ImageBufferSize);
  195.       }
  196.       FreeMem(gl, (LONG)(sizeof(struct GadgetList) +
  197.            (gl->gl_DataEntries - 1) * sizeof(struct ExtendedGadget *)));
  198.    }
  199. }
  200.     /* Display gadget list */
  201.  
  202.    VOID
  203. display_gadgets(struct Window  *win, struct GadgetList  *gl)
  204. {
  205.    if (win && gl && gl->gl_ID == ISUP_ID &&
  206.                  !(gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  207.       struct RenderInfo          *ri = gl->gl_RenderInfo;
  208.       struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  209.       struct ExtendedGadget      *last_egad;
  210.       USHORT i, data_entries = gl->gl_DataEntries,
  211.          clear_flags = (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW ?
  212.                     0 : CLEAR_WINDOW_FLAG_ABSOLUTE_POS);
  213.       /* Mark gadget list as displayed */
  214.       gl->gl_Window = win;
  215.       gl->gl_Flags |= GADGET_LIST_FLAG_DISPLAYED;
  216.  
  217.       /* Increment visible gadget list counter */
  218.       ObtainSemaphore(&vg->vg_Semaphore);
  219.       AddTail((struct List *)&vg->vg_MinList, (struct Node *)&gl->gl_MinNode);
  220.       vg->vg_Count++;
  221.       ReleaseSemaphore(&vg->vg_Semaphore);
  222.  
  223.       /* Link gadget list */
  224.       for (i = 0, last_egad = NULL; i < data_entries; i++) {
  225.      struct ExtendedGadget  *egad = gl->gl_Gadgets[i];
  226.  
  227.      /* First clear area occupied by this ISUP object */
  228.      if (!(egad->eg_DataFlags & GADGET_DATA_FLAG_NO_CLEAR)) {
  229.         clear_window(ri, win, egad->eg_BorderLeftEdge,
  230.                    egad->eg_BorderTopEdge, egad->eg_BorderWidth,
  231.                       egad->eg_BorderHeight, clear_flags);
  232.      }
  233.  
  234.      /* Move mouse pointer to this ISUP object */
  235.      if (egad->eg_DataFlags & GADGET_DATA_FLAG_MOVE_POINTER) {
  236.         struct Gadget  *gad = &egad->eg_Gadget;
  237.  
  238.         move_mouse_pointer(win, gad->LeftEdge + gad->Width / 2,
  239.                      gad->TopEdge + gad->Height / 2, FALSE);
  240.      }
  241.  
  242.      /* Link gadgets of this ISUP object */
  243.      do {
  244.         if (last_egad) {
  245.            last_egad->eg_Gadget.NextGadget = &egad->eg_Gadget;
  246.         }
  247.         last_egad = egad;
  248.      } while (egad = egad->eg_NextGadget);
  249.       }
  250.  
  251.       /* Mark end of gadget list */
  252.       if (last_egad) {
  253.      last_egad->eg_Gadget.NextGadget = NULL;
  254.       }
  255.  
  256.       /* Append new gadgets to window's gadget list and refresh them */
  257.       AddGList(win, &gl->gl_Gadgets[0]->eg_Gadget, -1L, -1L, (LONG)NULL);
  258.       refresh_gadgets(gl);
  259.    }
  260. }
  261.     /* Refresh gadget list */
  262.  
  263.    VOID
  264. refresh_gadgets(struct GadgetList  *gl)
  265. {
  266.    if (gl && gl->gl_ID == ISUP_ID &&
  267.                   (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  268.       USHORT i, data_entries = gl->gl_DataEntries;
  269.  
  270.       for (i = 0; i < data_entries; i++) {
  271.      refresh_gadget(gl->gl_Gadgets[i]);
  272.       }
  273.    }
  274. }
  275.     /* Modify gadget position and dimension */
  276.  
  277.    VOID
  278. modify_gadget(struct GadgetList  *gl, USHORT data_entry, LONG left_edge,
  279.                    LONG top_edge, ULONG width, ULONG height)
  280. {
  281.    if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries &&
  282.      (left_edge != USE_CURRENT_VALUE || top_edge != USE_CURRENT_VALUE ||
  283.            width != USE_CURRENT_VALUE || height != USE_CURRENT_VALUE)) {
  284.       struct ExtendedGadget  *egad = gl->gl_Gadgets[data_entry];
  285.       VOID  *data = egad + 1;
  286.       SHORT dx, dy;
  287.  
  288.       /* Clear old gadget */
  289.       if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  290.      struct RenderInfo  *ri = gl->gl_RenderInfo;
  291.      struct RastPort    *rp = gl->gl_Window->RPort;
  292.      SHORT x, y;
  293.  
  294.      SetAPen(rp, (LONG)ri->ri_BackPen);
  295.      SetDrMd(rp, (LONG)JAM1);
  296.  
  297.      /* Clear gadget */
  298.      x = egad->eg_BorderLeftEdge;
  299.      y = egad->eg_BorderTopEdge;
  300.  
  301.      /* Inner window position needed ? */
  302.      if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
  303.         x += ri->ri_WindowBorderLeft;
  304.         y += ri->ri_WindowBorderTop;
  305.      }
  306.      RectFill(rp, (LONG)x, (LONG)y, (LONG)(x + egad->eg_BorderWidth - 1),
  307.                      (LONG)(y + egad->eg_BorderHeight - 1));
  308.      /* Clear gadget text - don't forget underscore !!! */
  309.      if (egad->eg_Text) {
  310.         x = egad->eg_Gadget.LeftEdge + egad->eg_TextLeftEdge;
  311.         y = egad->eg_Gadget.TopEdge + egad->eg_TextTopEdge;
  312.         RectFill(rp, (LONG)x, (LONG)y, (LONG)(x + egad->eg_TextWidth - 1),
  313.                    (LONG)(y + egad->eg_TextFont->tf_YSize));
  314.      }
  315.       }
  316.  
  317.       /* Calc difference to old position */
  318.       if (left_edge == USE_CURRENT_VALUE) {
  319.      dx = 0;
  320.       } else {
  321.      dx = left_edge - egad->eg_BorderLeftEdge;
  322.       }
  323.       if (top_edge == USE_CURRENT_VALUE) {
  324.      dy = 0;
  325.       } else {
  326.      dy = top_edge - egad->eg_BorderTopEdge;
  327.       }
  328.  
  329.       /* Move gadget */
  330.       if (dx || dy) {
  331.      struct ExtendedGadget  *eg = egad;
  332.  
  333.      /* Move all extended gadgets belonging to this object */
  334.      do {
  335.         eg->eg_BorderLeftEdge  += dx;
  336.         eg->eg_BorderTopEdge   += dy;
  337.         eg->eg_Gadget.LeftEdge += dx;
  338.         eg->eg_Gadget.TopEdge  += dy;
  339.          } while (eg = eg->eg_NextGadget);
  340.  
  341.      /* Move special gadget data */
  342.      switch (egad->eg_Type) {
  343.         case EXTENDED_GADGET_TYPE_CYCLE :
  344.            ((struct CycleData *)data)->cy_LeftEdge += dx;
  345.            ((struct CycleData *)data)->cy_TopEdge  += dy;
  346.            break;
  347.  
  348.         case EXTENDED_GADGET_TYPE_COUNT :
  349.            ((struct CountData *)data)->co_LeftEdge += dx;
  350.            ((struct CountData *)data)->co_TopEdge  += dy;
  351.            break;
  352.  
  353.         case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  354.            ((struct ListViewData *)data)->lv_LeftEdge += dx;
  355.            ((struct ListViewData *)data)->lv_TopEdge  += dy;
  356.            break;
  357.      }
  358.       }
  359.  
  360.       /* Calc difference to old dimension */
  361.       if (width == USE_CURRENT_VALUE) {
  362.      dx = 0;
  363.       } else {
  364.      dx = width - egad->eg_BorderWidth;
  365.       }
  366.       if (height == USE_CURRENT_VALUE) {
  367.      dy = 0;
  368.       } else {
  369.      dy = height - egad->eg_BorderHeight;
  370.       }
  371.  
  372.       /* Resize only some gadgets */
  373.       if (dx || dy) {
  374.      struct Border  *border1 = NULL, *border2 = NULL;
  375.      USHORT border1_type, border2_type;
  376.      ULONG  flags = egad->eg_DataFlags;
  377.      BOOL   resize = FALSE;
  378.  
  379.      switch (egad->eg_Type) {
  380.         case EXTENDED_GADGET_TYPE_BUTTON :
  381.            if (!(flags & GADGET_DATA_FLAG_BUTTON_IMAGE)) {
  382.           border1_type = BORDER_DATA_TYPE_BOX1_OUT;
  383.           border1      = (struct Border *)
  384.                            egad->eg_Gadget.GadgetRender;
  385.           if (!(flags & GADGET_DATA_FLAG_HIGH_COMP)) {
  386.              border2_type = BORDER_DATA_TYPE_BOX1_IN;
  387.              border2      = (struct Border *)
  388.                            egad->eg_Gadget.SelectRender;
  389.           }
  390.           resize = TRUE;
  391.            }
  392.            break;
  393.  
  394.         case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  395.            border1_type = BORDER_DATA_TYPE_BOX1_OUT;
  396.            border1      = (struct Border *)egad->eg_Render;
  397.            resize       = TRUE;
  398.            break;
  399.  
  400.         case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  401.            if (flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS) {
  402.           border1_type = BORDER_DATA_TYPE_BOX1_OUT;
  403.           border1      = (struct Border *)egad->eg_Render;
  404.           resize       = TRUE;
  405.            }
  406.            break;
  407.  
  408.         case EXTENDED_GADGET_TYPE_COUNT :
  409.            border1_type = BORDER_DATA_TYPE_BOX1_OUT;
  410.            border1      = (struct Border *)egad->eg_Gadget.GadgetRender;
  411.            resize       = TRUE;
  412.  
  413.            /* Move area for current value */
  414.            ((struct CountData *)data)->co_LeftEdge =
  415.             egad->eg_Gadget.LeftEdge + (egad->eg_Gadget.Width + dx -
  416.                   ((struct CountData *)data)->co_Width) / 2;
  417.            ((struct CountData *)data)->co_TopEdge  =
  418.             egad->eg_Gadget.TopEdge + (egad->eg_Gadget.Height + dy -
  419.                  ((struct CountData *)data)->co_Height) / 2;
  420.            break;
  421.      }
  422.      if (resize == TRUE) {
  423.         
  424.         /* Resize gadget */
  425.         egad->eg_BorderWidth   += dx;
  426.         egad->eg_BorderHeight  += dy;
  427.         egad->eg_Gadget.Width  += dx;
  428.         egad->eg_Gadget.Height += dy;
  429.  
  430.         /* Resize gadget text */
  431.         if (egad->eg_Text) {
  432.  
  433.            /* Change horizontal pos */
  434.            if (flags & GADGET_DATA_FLAG_TEXT_RIGHT) {
  435.           egad->eg_TextLeftEdge += dx;
  436.            } else {
  437.           if (!(flags & GADGET_DATA_FLAG_TEXT_LEFT)) {
  438.              egad->eg_TextLeftEdge += dx / 2;
  439.           }
  440.            }
  441.  
  442.            /* Change vertical pos */
  443.            if (flags & GADGET_DATA_FLAG_TEXT_BELOW) {
  444.           egad->eg_TextTopEdge += dy;
  445.            } else {
  446.           if (!(flags & GADGET_DATA_FLAG_TEXT_ABOVE)) {
  447.              egad->eg_TextTopEdge += dy / 2;
  448.           }
  449.            }
  450.         }
  451.  
  452.         /* Resize border */
  453.         if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  454.            if (border1) {
  455.           resize_border(border1, egad->eg_BorderWidth,
  456.                        egad->eg_BorderHeight, border1_type);
  457.            }
  458.            if (border2) {
  459.           resize_border(border2, egad->eg_BorderWidth,
  460.                        egad->eg_BorderHeight, border2_type);
  461.            }
  462.         }
  463.      }
  464.       }
  465.  
  466.       /* Finally refresh modified gadget */
  467.       refresh_gadget(egad);
  468.    }
  469. }
  470.     /* Set gadget attributes */
  471.  
  472.    ULONG
  473. set_gadget_attributes(struct GadgetList  *gl, USHORT data_entry,
  474.     ULONG flag_mask, ULONG flag_bits, ULONG data1, ULONG data2, VOID *data3)
  475. {
  476.    ULONG value = 0;
  477.  
  478.    if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries) {
  479.       struct ExtendedGadget  *egad = gl->gl_Gadgets[data_entry];
  480.       struct Gadget          *gad = &egad->eg_Gadget;
  481.       USHORT type = egad->eg_DataType;
  482.       ULONG  flags = egad->eg_DataFlags;
  483.       BOOL   refresh = FALSE;
  484.  
  485.       /* Change gadget data flags */
  486.       if (flag_mask) {
  487.      ULONG  mask;
  488.      USHORT i;
  489.  
  490.      /* Change gadget data flags according to flag mask */
  491.      for (i = 0, mask = 1; i < MAX_DATA_FLAG_BITS; i++, mask <<= 1) {
  492.  
  493.         /* Check if flag bit set */
  494.         if (flag_mask & mask) {
  495.            BOOL change = FALSE;
  496.  
  497.            /* Change flag only if changeable and valid for gadget type */
  498.            switch (mask) {
  499.           case GADGET_DATA_FLAG_DISABLED :
  500.  
  501.              /* Toggle able state of gadget */
  502.              if ((flags & mask) != (flag_bits & mask)) {
  503.             struct RastPort        *rp;   /* init later !!! */
  504.             struct ExtendedGadget  *temp_egad = egad;
  505.             UBYTE displayed = gl->gl_Flags &
  506.                          GADGET_LIST_FLAG_DISPLAYED;
  507.             /* Set draw mode and color for clearing enabled select box */
  508.             if (displayed &&
  509.                       (flags & GADGET_DATA_FLAG_DISABLED)) {
  510.                rp = gl->gl_Window->RPort;   /* ONLY if displayed then gl_Window is valid !!!*/
  511.                SetDrMd(rp, (LONG)JAM1);
  512.                SetAPen(rp, (LONG)gl->gl_RenderInfo->ri_BackPen);
  513.             }
  514.  
  515.             /* Toggle able state of ALL gadgets belonging to ISUP object */
  516.             do {
  517.                struct Gadget  *temp_gad = &temp_egad->eg_Gadget;
  518.  
  519.                if (flags & GADGET_DATA_FLAG_DISABLED) {
  520.                   temp_gad->Flags &= ~GADGDISABLED;
  521.  
  522.                   /* Clear ghosted gadget select box */
  523.                   if (displayed) {
  524.                  RectFill(rp, (LONG)temp_gad->LeftEdge,
  525.                             (LONG)temp_gad->TopEdge,
  526.                          (LONG)(temp_gad->LeftEdge +
  527.                                temp_gad->Width - 1),
  528.                           (LONG)(temp_gad->TopEdge +
  529.                              temp_gad->Height - 1));
  530.                   }
  531.                } else {
  532.                   temp_gad->Flags |= GADGDISABLED;
  533.                }
  534.             } while (temp_egad = temp_egad->eg_NextGadget);
  535.  
  536.             /* Refresh gadget before leaving function */
  537.             refresh = TRUE;
  538.             change  = TRUE;
  539.              }
  540.              break;
  541.  
  542.           case GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE :
  543.              if (type == GADGET_DATA_TYPE_STRING ||
  544.                      type == GADGET_DATA_TYPE_INTEGER) {
  545.             change = TRUE;
  546.              }
  547.              break;
  548.  
  549.           case GADGET_DATA_FLAG_STRING_UNSIGNED_DEC :
  550.              if (type == GADGET_DATA_TYPE_STRING) {
  551.             change = TRUE;
  552.              }
  553.              break;
  554.  
  555.           case GADGET_DATA_FLAG_STRING_SIGNED_DEC :
  556.              if (type == GADGET_DATA_TYPE_STRING) {
  557.             change = TRUE;
  558.              }
  559.              break;
  560.  
  561.           case GADGET_DATA_FLAG_STRING_HEX :
  562.              if (type == GADGET_DATA_TYPE_STRING) {
  563.             change = TRUE;
  564.              }
  565.              break;
  566.  
  567.           case GADGET_DATA_FLAG_STRING_BIN :
  568.              if (type == GADGET_DATA_TYPE_STRING) {
  569.             change = TRUE;
  570.              }
  571.              break;
  572.  
  573.           case GADGET_DATA_FLAG_MOVE_POINTER :
  574.              change = TRUE;
  575.              break;
  576.            }
  577.  
  578.            /* Change flag bit if neccessary */
  579.            if (change == TRUE) {
  580.           flags &= ~mask;
  581.           flags |= flag_bits & mask;
  582.            }
  583.         }
  584.      }
  585.  
  586.      /* Save changed gadget data flags */
  587.      egad->eg_DataFlags = flags;
  588.       }
  589.  
  590.       /* Get current setting and change special gadget data */
  591.       switch (type) {
  592.      case GADGET_DATA_TYPE_BUTTON :
  593.         if (gad->Activation & TOGGLESELECT) {
  594.            if (gad->Flags & SELECTED) {
  595.           value = 1;
  596.            }
  597.            if (data1 != USE_CURRENT_VALUE) {
  598.           if (data1) {
  599.              gad->Flags |= SELECTED;
  600.           } else {
  601.              if (gad->Flags & SELECTED) {
  602.  
  603.             /* Prepare gadget state manually (unselected) */
  604.             change_gadget(egad);
  605.              }
  606.              gad->Flags &= ~SELECTED;
  607.           }
  608.           change_gadget(egad);
  609.            }
  610.         }
  611.         break;
  612.  
  613.      case GADGET_DATA_TYPE_CHECK :
  614.         if (gad->Flags & SELECTED) {
  615.             value = 1;
  616.         }
  617.         if (data1 != USE_CURRENT_VALUE) {
  618.            if (data1) {
  619.           gad->Flags |= SELECTED;
  620.            } else {
  621.           gad->Flags &= ~SELECTED;
  622.            }
  623.            change_gadget(egad);
  624.         }
  625.         break;
  626.  
  627.      case GADGET_DATA_TYPE_MX :
  628.         {
  629.            struct MXData  *mx = (VOID *)(egad + 1);
  630.  
  631.            value = mx->mx_ActiveEntry;
  632.            if (data2 != USE_CURRENT_VALUE) {
  633.           ULONG entries = mx->mx_TextEntries, active = data2;
  634.  
  635.           if (active >= entries) {
  636.              active = entries - 1;   /* activate last entry */
  637.           }
  638.           mx->mx_ActiveEntry = active;
  639.           change_gadget(egad);
  640.            }
  641.         }
  642.         break;
  643.  
  644.      case GADGET_DATA_TYPE_STRING :
  645.      case GADGET_DATA_TYPE_INTEGER :
  646.         {
  647.            struct StringInfo  *sinfo = (struct StringInfo *)
  648.                                gad->SpecialInfo;
  649.            BYTE *buffer = (BYTE *)sinfo->Buffer;
  650.  
  651.            if (type == GADGET_DATA_TYPE_STRING) {
  652.           value = (ULONG)buffer;
  653.            } else {
  654.           value = sinfo->LongInt;
  655.            }
  656.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  657.           BYTE  *input = data3;
  658.           ULONG len, max_len = sinfo->MaxChars;
  659.  
  660.           if (type == GADGET_DATA_TYPE_STRING) {
  661.  
  662.              /* Convert number for string input gadget */
  663.              if (flags & GADGET_DATA_FLAG_STRING_UNSIGNED_DEC) {
  664.             if ((LONG)input != -1L) {
  665.                len = convert_unsigned_dec((ULONG)input,
  666.                          buffer, DEC_NUM_CONVERT_FLAGS);
  667.             } else {
  668.                len = 0;
  669.             }
  670.              } else {
  671.             if (flags & GADGET_DATA_FLAG_STRING_SIGNED_DEC) {
  672.                if ((LONG)input != -1L) {
  673.                   len = convert_signed_dec((ULONG)input, buffer,
  674.                              DEC_NUM_CONVERT_FLAGS);
  675.                } else {
  676.                   len = 0;
  677.                }
  678.             } else {
  679.                if (flags & GADGET_DATA_FLAG_STRING_HEX) {
  680.                   if ((LONG)input != -1L) {
  681.                  len = convert_hex((ULONG)input, buffer,
  682.                              HEX_NUM_CONVERT_FLAGS);
  683.                   } else {
  684.                  len = 0;
  685.                   }
  686.                } else {
  687.                   if (flags & GADGET_DATA_FLAG_STRING_BIN) {
  688.                  if ((LONG)input != -1L) {
  689.                     len = convert_bin((ULONG)input, buffer,
  690.                              BIN_NUM_CONVERT_FLAGS);
  691.                  } else {
  692.                     len = 0;
  693.                  }
  694.                   } else {
  695.                  if (input) {
  696.                     if ((len = strlen(input)) > max_len) {
  697.                        len = max_len;
  698.                     }
  699.                     strncpy(buffer, input, (size_t)len);
  700.                  } else {
  701.                     len = 0;
  702.                  }
  703.                   }
  704.                }
  705.             }
  706.              }
  707.           } else {
  708.  
  709.              /* Convert number for integer input gadget */
  710.              if ((LONG)input != -1L) {
  711.             len = convert_unsigned_dec((ULONG)input, buffer, 0);
  712.              } else {
  713.             len = 0;
  714.              }
  715.           }
  716.           *(buffer + len)  = '\0';   /* mark end of string */
  717.           sinfo->BufferPos = 0;
  718.           change_gadget(egad);
  719.            }
  720.         }
  721.         break;
  722.  
  723.      case GADGET_DATA_TYPE_SLIDER :
  724.         {
  725.            struct SliderData  *sl = (VOID *)(egad + 1);
  726.  
  727.            value = sl->sl_Level;
  728.            if (data1 != USE_CURRENT_VALUE || data2 != USE_CURRENT_VALUE
  729.                      || (ULONG)data3 != USE_CURRENT_VALUE) {
  730.           ULONG min, max, level;
  731.  
  732.           if (data1 != USE_CURRENT_VALUE) {
  733.              min = sl->sl_Min = data1;
  734.           } else {
  735.             min = sl->sl_Min;
  736.           }
  737.           if (data2 != USE_CURRENT_VALUE) {
  738.              max = sl->sl_Max = data2;
  739.           } else {
  740.              max = sl->sl_Max;
  741.           }
  742.           if ((ULONG)data3 != USE_CURRENT_VALUE) {
  743.              level = (ULONG)data3;
  744.           } else {
  745.              level = sl->sl_Level;
  746.           }
  747.           if ((LONG)level < (LONG)min) {
  748.              level = min;
  749.           } else {
  750.             if ((LONG)level > (LONG)max) {
  751.                level = max;
  752.             }
  753.           }
  754.           sl->sl_Level = level;
  755.           change_gadget(egad);
  756.            }
  757.         }
  758.         break;
  759.  
  760.      case GADGET_DATA_TYPE_SCROLLER :
  761.         {
  762.            struct ScrollerData  *sc = (VOID *)(egad + 1);
  763.  
  764.            value = sc->sc_Top;
  765.            if (data1 != USE_CURRENT_VALUE || data2 != USE_CURRENT_VALUE
  766.                      || (ULONG)data3 != USE_CURRENT_VALUE) {
  767.               ULONG visible, total, top;
  768.  
  769.           if (data1 != USE_CURRENT_VALUE) {
  770.              visible = sc->sc_Visible = data1;
  771.           } else {
  772.              visible = sc->sc_Visible;
  773.           }
  774.           if (data2 != USE_CURRENT_VALUE) {
  775.              total = sc->sc_Total = data2;
  776.           } else {
  777.              total = sc->sc_Total;
  778.           }
  779.           if ((ULONG)data3 != USE_CURRENT_VALUE) {
  780.              top = (ULONG)data3;
  781.           } else {
  782.              top = sc->sc_Top;
  783.           }
  784.           if (top >= total || (total - top) < visible) {
  785.              top = (total > visible ? total - visible :
  786.                                visible - total);
  787.           }
  788.           sc->sc_Top = top;
  789.           change_gadget(egad);
  790.            }
  791.         }
  792.         break;
  793.  
  794.      case GADGET_DATA_TYPE_CYCLE :
  795.         {
  796.            struct CycleData  *cy = (VOID *)(egad + 1);
  797.  
  798.            value = cy->cy_ActiveEntry;
  799.            if (data2 != USE_CURRENT_VALUE) {
  800.           ULONG entries = cy->cy_TextEntries, active = data2;
  801.  
  802.           if (active > entries) {
  803.              active = entries;   /* activate last entry */
  804.           }
  805.           cy->cy_ActiveEntry = active;
  806.           change_gadget(egad);
  807.            }
  808.         }
  809.         break;
  810.  
  811.      case GADGET_DATA_TYPE_COUNT :
  812.         {
  813.            struct CountData  *co = (VOID *)(egad + 1);
  814.  
  815.            value = co->co_Value;
  816.            if (data1 != USE_CURRENT_VALUE || data2 != USE_CURRENT_VALUE
  817.                      || (ULONG)data3 != USE_CURRENT_VALUE) {
  818.           if ((ULONG)data1 != USE_CURRENT_VALUE ||
  819.                     (ULONG)data2 != USE_CURRENT_VALUE) {
  820.              struct IntuiText  itext;
  821.              USHORT min_len, max_len, width;
  822.              SHORT  left_edge;
  823.              ULONG  min, max;
  824.  
  825.              /* Calc new left edge and width of area for count value */
  826.              if ((ULONG)data1 != USE_CURRENT_VALUE) {
  827.             min = (ULONG)data1;
  828.              } else {
  829.             min = co->co_Min;
  830.              }
  831.              if ((ULONG)data2 != USE_CURRENT_VALUE) {
  832.             max = (ULONG)data2;
  833.              } else {
  834.             max = co->co_Max;
  835.              }
  836.              if (flags & GADGET_DATA_FLAG_COUNT_SIGNED_DEC) {
  837.             min_len = convert_signed_dec((LONG)min,
  838.                                (BYTE *)NULL, 0);
  839.             max_len = convert_signed_dec((LONG)max,
  840.                                (BYTE *)NULL, 0);
  841.              } else {
  842.             min_len = convert_unsigned_dec(min, (BYTE *)NULL, 0);
  843.             max_len = convert_unsigned_dec(max, (BYTE *)NULL, 0);
  844.              }
  845.              itext.ITextFont = egad->eg_TextAttr;
  846.              itext.IText     = (UBYTE *)"8";
  847.              width           = IntuiTextLength(&itext) *
  848.                     (min_len > max_len ? min_len : max_len);
  849.              left_edge       = gad->LeftEdge +
  850.                         (SHORT)(gad->Width - width) / 2;
  851.              /* Clear old area */
  852.              if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  853.             print_count_text(egad, FALSE);
  854.              }
  855.  
  856.              /* Change count data */
  857.              co->co_LeftEdge = left_edge;
  858.              co->co_Width    = width;
  859.              co->co_Min      = min;
  860.              co->co_Max      = max;
  861.  
  862.              /* Now let's compare current value with new bounds */
  863.              if ((ULONG)data3 == USE_CURRENT_VALUE) {
  864.             data3 = (VOID *)co->co_Value;
  865.              }
  866.           }
  867.           if ((ULONG)data3 != USE_CURRENT_VALUE) {
  868.              ULONG min = co->co_Min, max = co->co_Max,
  869.                num = (ULONG)data3;
  870.  
  871.              /* Compare new current value with bounds */
  872.              if ((LONG)num < (LONG)min) {
  873.             num = min;
  874.              } else {
  875.             if ((LONG)num > (LONG)max) {
  876.                num = max;
  877.             }
  878.              }
  879.              co->co_Value = num;
  880.              change_gadget(egad);
  881.           }
  882.            }
  883.         }
  884.         break;
  885.  
  886.      case GADGET_DATA_TYPE_LISTVIEW :
  887.         {
  888.            struct ListViewData  *lv = (VOID *)(egad + 1);
  889.  
  890.            if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  891.           value = lv->lv_SelectedEntry;
  892.            } else {
  893.           value = lv->lv_TopEntry;
  894.            }
  895.            if (data2 != USE_CURRENT_VALUE ||
  896.                     (ULONG)data3 != USE_CURRENT_VALUE) {
  897.           ULONG visible, entries, top;
  898.  
  899.           if ((ULONG)data3 != USE_CURRENT_VALUE) {
  900.              struct List  *list = data3;
  901.              struct Node  *node;
  902.  
  903.              /* Count list nodes */
  904.              entries = 0;
  905.              if (list) {
  906.             node = list->lh_Head;
  907.             while (node = node->ln_Succ) {
  908.                entries++;
  909.             }
  910.              }
  911.              lv->lv_List        = list;
  912.              lv->lv_ListEntries = entries;
  913.           }
  914.           if (data2 != USE_CURRENT_VALUE ||
  915.                     (ULONG)data3 != USE_CURRENT_VALUE) {
  916.              struct List  *list = data3;
  917.              struct Node  *node;
  918.              ULONG sel;
  919.  
  920.              list    = lv->lv_List;
  921.              visible = lv->lv_VisibleEntries;
  922.              entries = lv->lv_ListEntries;
  923.  
  924.              /* Search top list node */
  925.              if (!entries) {
  926.             sel  = 0;
  927.             top  = 0;
  928.             node = NULL;
  929.              } else {
  930.             if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  931.  
  932.                /* Calc correct top entry for selected entry */
  933.                if (data2 != USE_CURRENT_VALUE) {
  934.                   sel = data2;
  935.                } else {
  936.                   sel = lv->lv_SelectedEntry;
  937.                }
  938.                if (sel >= entries) {
  939.                   sel = entries - 1;
  940.                }
  941.                if (sel && entries > visible) {
  942.                   if (sel > (entries - visible)) {
  943.                  ULONG i;
  944.  
  945.                  top  = entries - visible;
  946.                  node = list->lh_TailPred;
  947.                  for (i = entries - top - 1; i; i--) {
  948.                     node = node->ln_Pred;
  949.                  }
  950.                   } else {
  951.                  node = list->lh_Head;
  952.                  if (sel > (visible >> 1)) {
  953.                     ULONG i;
  954.  
  955.                     top = sel - (visible >> 1);
  956.                     for (i = 0; i < top; i++) {
  957.                        node = node->ln_Succ;
  958.                     }
  959.                  } else {
  960.                     top = 0;
  961.                  }
  962.                   }
  963.                } else {
  964.                   top  = 0;
  965.                   node = list->lh_Head;
  966.                }
  967.             } else {
  968.  
  969.                /* Calc top entry ignoring selected entry */
  970.                if (data2 != USE_CURRENT_VALUE) {
  971.                   top = data2;
  972.                } else {
  973.                   top = lv->lv_TopEntry;
  974.                }
  975.                if (top && entries > visible) {
  976.                   if (top > entries ||
  977.                         (entries - top) < visible) {
  978.                  ULONG i;
  979.  
  980.                  top  = entries - visible;
  981.                  node = list->lh_TailPred;
  982.                  for (i = entries - top - 1; i; i--) {
  983.                     node = node->ln_Pred;
  984.                  }
  985.                   } else {
  986.                  ULONG i;
  987.  
  988.                  node = list->lh_Head;
  989.                  for (i = 0; i < top; i++) {
  990.                     node = node->ln_Succ;
  991.                  }
  992.                   }
  993.                } else {
  994.                   top  = 0;
  995.                   node = list->lh_Head;
  996.                }
  997.                sel = top;
  998.             }
  999.              }
  1000.  
  1001.              /* Init list view data */
  1002.              lv->lv_TopNode       = node;
  1003.              lv->lv_TopEntry      = top;
  1004.              lv->lv_SelectedEntry = sel;
  1005.              change_gadget(egad);   /* before changing list entry gadget flags !!! */
  1006.  
  1007.              /* Set GADGHNONE flag for all entry gadgets without list node */
  1008.              if (!(flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY)) {
  1009.             struct ExtendedGadget  *temp_egad;
  1010.             USHORT i;
  1011.  
  1012.             /* Get ptr to first entry gadget */
  1013.             temp_egad = egad->eg_NextGadget->eg_NextGadget->
  1014.                                   eg_NextGadget;
  1015.             for (i = 0; i < visible; i++, top++) {
  1016.                struct Gadget  *temp_gad = &temp_egad->eg_Gadget;
  1017.  
  1018.                if (top < entries) {
  1019.                   temp_gad->Flags = (temp_gad->Flags &
  1020.                          ~GADGHIGHBITS) | GADGHCOMP;
  1021.                } else {
  1022.                   temp_gad->Flags = (temp_gad->Flags &
  1023.                          ~GADGHIGHBITS) | GADGHNONE;
  1024.                }
  1025.                temp_egad = temp_egad->eg_NextGadget;
  1026.             }
  1027.              }
  1028.           }
  1029.            }
  1030.         }
  1031.         break;
  1032.  
  1033.      case GADGET_DATA_TYPE_PALETTE :
  1034.         {
  1035.            struct PaletteData  *pd = (VOID *)(egad + 1);
  1036.  
  1037.            value = pd->pd_ActiveColor;
  1038.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  1039.           ULONG offset = pd->pd_ColorOffset, max = pd->pd_MaxColors,
  1040.             active = (ULONG)data3;
  1041.  
  1042.           if (active < offset) {
  1043.              active = offset;
  1044.           } else {
  1045.              if (active >= (max + offset)) {
  1046.             active = max + offset - 1;
  1047.              }
  1048.           }
  1049.           pd->pd_ActiveColor = active;
  1050.           change_gadget(egad);
  1051.            }
  1052.         }
  1053.         break;
  1054.       }
  1055.  
  1056.       /* Finally refresh gadget if necessary */
  1057.       if (refresh == TRUE) {
  1058.      refresh_gadget(egad);
  1059.       }
  1060.    }
  1061.    return(value);
  1062. }
  1063.     /* Activate string or integer input gadget */
  1064.  
  1065.    VOID
  1066. activate_input_gadget(struct GadgetList  *gl, USHORT data_entry)
  1067. {
  1068.    if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries &&
  1069.                   (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  1070.       struct ExtendedGadget  *egad = gl->gl_Gadgets[data_entry];
  1071.       USHORT type = egad->eg_DataType;
  1072.  
  1073.       if (type == GADGET_DATA_TYPE_STRING ||
  1074.                      type == GADGET_DATA_TYPE_INTEGER) {
  1075.      struct Gadget  *gad = &egad->eg_Gadget;
  1076.  
  1077.      /* If selected input gadget disabled then activate next one */
  1078.      if (gad->Flags & GADGDISABLED) {
  1079.         if (egad->eg_DataFlags & GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE) {
  1080.            struct InputData  *id = (struct InputData  *)(egad + 1);
  1081.  
  1082.            /* !!! Recurrence (in german: Rekursion) !!! */
  1083.            activate_input_gadget(gl, id->id_ActivateNext);
  1084.         }
  1085.      } else {
  1086.         struct Window  *win = gl->gl_Window;
  1087.  
  1088.         /* First bring screen + window to front */
  1089.         if (IntuitionBase->ActiveScreen != win->WScreen) {
  1090.            ScreenToFront(win->WScreen);
  1091.         }
  1092.  
  1093.         /* Now activate window + input gadget */
  1094.         if (IntuitionBase->ActiveWindow != win) {
  1095.            WindowToFront(win);
  1096.            ActivateWindow(win);
  1097.            timer_delay(0L, 500000L);
  1098.         }
  1099.         ActivateGadget(gad, win, (LONG)NULL);
  1100.      }
  1101.       }
  1102.    }
  1103. }
  1104.     /* Return gadget address */
  1105.  
  1106.    struct Gadget *
  1107. gadget_address(struct GadgetList  *gl, USHORT data_entry)
  1108. {
  1109.    struct Gadget  *gad = NULL;
  1110.  
  1111.    if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries) {
  1112.       gad = &gl->gl_Gadgets[data_entry]->eg_Gadget;
  1113.    }
  1114.    return(gad);
  1115. }
  1116.     /* Remove gadget list from display */
  1117.  
  1118.    struct Window *
  1119. remove_gadgets(struct GadgetList  *gl)
  1120. {
  1121.    struct Window  *win = NULL;
  1122.  
  1123.    if (gl && gl->gl_ID == ISUP_ID &&
  1124.                   (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  1125.       struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1126.       struct IntuiMessage        *succ, *msg;
  1127.       USHORT i, data_entries = gl->gl_DataEntries;
  1128.  
  1129.       /* Mark gadget list as not displayed */
  1130.       win           = gl->gl_Window;
  1131.       gl->gl_Window = NULL;
  1132.       gl->gl_Flags &= ~GADGET_LIST_FLAG_DISPLAYED;
  1133.  
  1134.       /* Decrement visible gadget list counter */
  1135.       ObtainSemaphore(&vg->vg_Semaphore);
  1136.       Remove((struct Node *)&gl->gl_MinNode);
  1137.       vg->vg_Count--;
  1138.       ReleaseSemaphore(&vg->vg_Semaphore);
  1139.  
  1140.       /* Remove gadgets from windows gadget list */
  1141.       for (i = 0; i < data_entries; i++) {
  1142.      struct ExtendedGadget  *egad = gl->gl_Gadgets[i];
  1143.  
  1144.      do {
  1145.         RemoveGList(win, &egad->eg_Gadget, 1L);
  1146.      } while (egad = egad->eg_NextGadget);
  1147.       }
  1148.  
  1149.       /* Reply all ISUP intuition messages belonging to this window */
  1150.       Forbid();
  1151.       msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
  1152.       while (succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ) {
  1153.      if (msg->IDCMPWindow == win) {
  1154.         switch (msg->Class) {
  1155.            case GADGETDOWN :
  1156.            case GADGETUP :
  1157.            case MOUSEMOVE :
  1158.            case INTUITICKS :
  1159.            case VANILLAKEY :    /* for compatibility to < v4.2 only */
  1160.            case RAWKEY :
  1161.           Remove((struct Node *)msg);
  1162.           ReplyMsg((struct Message *)msg);
  1163.           break;
  1164.         }
  1165.      }
  1166.      msg = succ;
  1167.       }
  1168.       Permit();
  1169.    }
  1170.    return(win);
  1171. }
  1172.     /* Get intuition msg and perform any action to isup gadgets */
  1173.  
  1174.    struct IntuiMessage *
  1175. get_msg(struct MsgPort  *uport)
  1176. {
  1177.    struct IntuiMessage  *imsg = NULL;
  1178.  
  1179.    if (uport) {
  1180.       struct IntuiMessage  *real_imsg;
  1181.  
  1182.       while (imsg == NULL && (real_imsg = (struct IntuiMessage *)
  1183.                                GetMsg(uport))) {
  1184.      struct ExtendedGadget  *egad;
  1185.  
  1186.      switch (real_imsg->Class) {
  1187.         case GADGETDOWN :
  1188.            egad = (struct ExtendedGadget *)real_imsg->IAddress;
  1189.            if (egad->eg_Gadget.MutualExclude == ISUP_ID) {
  1190.           USHORT activation = egad->eg_Gadget.Activation;
  1191.  
  1192.           /* Perform gadget action and check activation flags */
  1193.           imsg = perform_gadget_action(egad, real_imsg);
  1194.           if ((activation & FOLLOWMOUSE) ||
  1195.                    (activation & (GADGIMMEDIATE | RELVERIFY)) ==
  1196.                           (GADGIMMEDIATE | RELVERIFY)) {
  1197.              struct GadgetList  *gl = egad->eg_GadgetList;
  1198.  
  1199.              /* Save active gadget and set auto repeat delay counter */
  1200.              gl->gl_ActiveGadget    = egad;
  1201.              gl->gl_AutoRepeatDelay = ARROW_AUTO_REPEAT_START_DELAY;
  1202.           }
  1203.            } else {
  1204.           egad = NULL;   /* return imsg later */
  1205.            }
  1206.            break;
  1207.  
  1208.         case GADGETUP :
  1209.            egad = (struct ExtendedGadget *)real_imsg->IAddress;
  1210.            if (egad->eg_Gadget.MutualExclude == ISUP_ID) {
  1211.           imsg = perform_gadget_action(egad, real_imsg);
  1212.  
  1213.           /* Reset saved active gadget */
  1214.           egad->eg_GadgetList->gl_ActiveGadget = NULL;
  1215.             } else {
  1216.           egad = NULL;   /* return imsg later */
  1217.            }
  1218.            break;
  1219.  
  1220.         case MOUSEMOVE :
  1221.            if (egad = get_active_gadget(real_imsg->IDCMPWindow)) {
  1222.           imsg = perform_gadget_action(egad, real_imsg);
  1223.            }
  1224.            break;
  1225.  
  1226.         case INTUITICKS :
  1227.            if ((egad = get_active_gadget(real_imsg->IDCMPWindow))
  1228.                     && (egad->eg_Gadget.Flags &    SELECTED)) {
  1229.           if ((egad->eg_Gadget.Activation & (GADGIMMEDIATE |
  1230.                    RELVERIFY)) == (GADGIMMEDIATE | RELVERIFY)) {
  1231.              struct GadgetList  *gl = egad->eg_GadgetList;
  1232.  
  1233.              /* Check and decrement auto repeat delay counter */
  1234.              if (gl->gl_AutoRepeatDelay) {
  1235.             gl->gl_AutoRepeatDelay--;
  1236.              } else {
  1237.             imsg = perform_gadget_action(egad, real_imsg);
  1238.              }
  1239.           }
  1240.            }
  1241.            break;
  1242.  
  1243.         case VANILLAKEY :    /* for compatibility to < v4.3 only */
  1244.            if (egad = get_hotkey_gadget(real_imsg->IDCMPWindow,
  1245.                              real_imsg->Code)) {
  1246.           if (!(egad->eg_Gadget.Flags & GADGDISABLED)) {
  1247.              imsg = perform_hotkey_action(egad, real_imsg);
  1248.           }
  1249.            }
  1250.            break;
  1251.  
  1252.         case RAWKEY :
  1253.            if (egad = get_hotkey_gadget(real_imsg->IDCMPWindow,
  1254.                       convert_rawkey_to_ascii(real_imsg))) {
  1255.           if (!(egad->eg_Gadget.Flags & GADGDISABLED)) {
  1256.              imsg = perform_hotkey_action(egad, real_imsg);
  1257.           }
  1258.            }
  1259.            break;
  1260.  
  1261.         default :
  1262.            if (egad = get_active_gadget(real_imsg->IDCMPWindow)) {
  1263.           egad->eg_GadgetList->gl_ActiveGadget = NULL;
  1264.           egad = NULL;   /* return imsg later */
  1265.            }
  1266.            break;
  1267.      }
  1268.      if (!imsg) {
  1269.  
  1270.         /* If isup msg then reply it, else return it */
  1271.         if (egad) {
  1272.            ReplyMsg((struct Message *)real_imsg);
  1273.         } else {
  1274.            imsg = real_imsg;
  1275.         }
  1276.      }
  1277.       }
  1278.    }
  1279.    return(imsg);
  1280. }
  1281.     /* Reply intuition message and free ISUP message if any */
  1282.  
  1283.    VOID
  1284. reply_msg(struct IntuiMessage  *imsg)
  1285. {
  1286.    if (imsg) {
  1287.       if (imsg->Class == ISUP_ID) {
  1288.      struct IntuiMessage  *real_imsg = *(struct IntuiMessage **)
  1289.                                  (imsg + 1);
  1290.      /* Free ISUP msg */
  1291.      FreeMem(imsg, (LONG)(sizeof(struct IntuiMessage) +
  1292.                         sizeof(struct IntuiMessage *)));
  1293.      /* Return real intui msg (ptr direct after ISUP msg) */
  1294.      imsg = real_imsg;
  1295.       }
  1296.       ReplyMsg((struct Message *)imsg);
  1297.    }
  1298. }
  1299.     /* Perform ISUP gadget action */
  1300.  
  1301.    STATIC struct IntuiMessage *
  1302. perform_gadget_action(struct ExtendedGadget  *egad,
  1303.                         struct IntuiMessage  *real_imsg)
  1304. {
  1305.    struct IntuiMessage    *imsg = NULL;
  1306.    struct Gadget          *gad = &egad->eg_Gadget;
  1307.    struct GadgetList      *gl = egad->eg_GadgetList;
  1308.    USHORT data_entry = egad->eg_DataEntry;
  1309.    struct ExtendedGadget  *real_egad = gl->gl_Gadgets[data_entry];
  1310.    struct MXData          *mx;
  1311.    struct ListViewData    *lv;
  1312.    struct PaletteData     *pd;
  1313.    VOID   *data = (VOID *)(real_egad + 1);
  1314.    USHORT type = egad->eg_Type;
  1315.    ULONG  min, max, num, flags = real_egad->eg_DataFlags, value = 0,
  1316.       class = real_imsg->Class, qualifier = real_imsg->Qualifier;
  1317.  
  1318.    switch (type) {
  1319.       case EXTENDED_GADGET_TYPE_BUTTON :
  1320.      if ((flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) &&
  1321.                           (gad->Flags & SELECTED)) {
  1322.         /* Prepare gadget state manually (selected) */
  1323.         change_gadget(real_egad);
  1324.         value = 1;
  1325.      }
  1326.      change_gadget(real_egad);
  1327.      break;
  1328.  
  1329.       case EXTENDED_GADGET_TYPE_CHECK :
  1330.      if (gad->Flags & SELECTED) {
  1331.         value = 1;
  1332.      }
  1333.      break;
  1334.  
  1335.       case EXTENDED_GADGET_TYPE_MX :
  1336.      mx = data;
  1337.      if (mx->mx_ActiveEntry != egad->eg_Gadget.GadgetID) {
  1338.         mx->mx_ActiveEntry = value = egad->eg_Gadget.GadgetID;
  1339.      } else {
  1340.         real_imsg = NULL;
  1341.      }
  1342.      change_gadget(real_egad);
  1343.      break;
  1344.  
  1345.       case EXTENDED_GADGET_TYPE_STRING :
  1346.       case EXTENDED_GADGET_TYPE_INTEGER :
  1347.      if (!(qualifier & QUALIFIER_ALT) &&
  1348.                (flags & GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE)) {
  1349.         struct InputData  *id = data;
  1350.         USHORT next_input;
  1351.  
  1352.         if (qualifier & QUALIFIER_SHIFT) {
  1353.            next_input = id->id_ActivatePrev;
  1354.         } else {
  1355.            next_input = id->id_ActivateNext;
  1356.         }
  1357.         activate_input_gadget(gl, next_input);
  1358.      }
  1359.      if (type == EXTENDED_GADGET_TYPE_STRING) {
  1360.         value = (ULONG)((struct StringInfo *)gad->SpecialInfo)->Buffer;
  1361.      } else {
  1362.         value = (ULONG)((struct StringInfo *)gad->SpecialInfo)->LongInt;
  1363.      }
  1364.      break;
  1365.  
  1366.       case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  1367.      if (class == GADGETUP) {
  1368.         change_gadget(real_egad);
  1369.         real_imsg = NULL;
  1370.      } else {
  1371.         struct SliderData  *sl = data;
  1372.         struct PropInfo    *pi = (struct PropInfo *)gad->SpecialInfo;
  1373.  
  1374.         min = sl->sl_Min;
  1375.         max = (LONG)sl->sl_Max - (LONG)min;
  1376.         if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  1377.            num = max - ((LONG)get_prop_pos(max + 1, 1L, pi->VertPot) -
  1378.                                  (LONG)min);
  1379.         } else {
  1380.            num = (LONG)get_prop_pos(max + 1, 1L, pi->HorizPot) +
  1381.                                   (LONG)min;
  1382.         }
  1383.         if (sl->sl_Level != num) {
  1384.            sl->sl_Level = value = num;
  1385.         } else {
  1386.            real_imsg = NULL;
  1387.         }
  1388.      }
  1389.      break;
  1390.  
  1391.       case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  1392.      if (class == GADGETUP) {
  1393.         change_gadget(real_egad);
  1394.         real_imsg = NULL;
  1395.      } else {
  1396.         struct ScrollerData  *sc = data;
  1397.         struct PropInfo      *pi = (struct PropInfo *)gad->SpecialInfo;
  1398.  
  1399.         min = sc->sc_Visible;
  1400.         max = sc->sc_Total;
  1401.         if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  1402.            num = get_prop_pos(max, min, pi->VertPot);
  1403.         } else {
  1404.            num = get_prop_pos(max, min, pi->HorizPot);
  1405.         }
  1406.         if (sc->sc_Top != num) {
  1407.            sc->sc_Top = value = num;
  1408.         } else {
  1409.            real_imsg = NULL;
  1410.         }
  1411.      }
  1412.      break;
  1413.  
  1414.       case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
  1415.       case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
  1416.      if (class == GADGETUP) {
  1417.         real_imsg = NULL;
  1418.      } else {
  1419.         struct ScrollerData  *sc = data;
  1420.  
  1421.         num = sc->sc_Top;
  1422.         if (num > 0) {
  1423.            sc->sc_Top = value = num - 1;
  1424.            change_gadget(real_egad);
  1425.         } else {
  1426.            real_imsg = NULL;
  1427.         }
  1428.      }
  1429.      break;
  1430.  
  1431.       case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
  1432.       case EXTENDED_GADGET_TYPE_SCROLLER_UP :
  1433.      if (class == GADGETUP) {
  1434.         real_imsg = NULL;
  1435.      } else {
  1436.         struct ScrollerData  *sc = data;
  1437.  
  1438.         num = sc->sc_Top;
  1439.         min = sc->sc_Visible;
  1440.         max = sc->sc_Total;
  1441.         num++;
  1442.         if (num < max && (max - num) >= min) {
  1443.            sc->sc_Top = value = num;
  1444.            change_gadget(real_egad);
  1445.         } else {
  1446.            real_imsg = NULL;
  1447.         }
  1448.      }
  1449.      break;
  1450.  
  1451.       case EXTENDED_GADGET_TYPE_CYCLE :
  1452.      if (change_cycle_gadget(real_egad, qualifier) == TRUE) {
  1453.         value = ((struct CycleData *)data)->cy_ActiveEntry;
  1454.      } else {
  1455.         real_imsg = NULL;
  1456.      }
  1457.      break;
  1458.  
  1459.       case EXTENDED_GADGET_TYPE_COUNT :
  1460.      change_count_gadget(real_egad);
  1461.      value = ((struct CountData *)data)->co_Value;
  1462.      break;
  1463.  
  1464.       case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  1465.      if (class == GADGETUP) {
  1466.         change_gadget(real_egad);
  1467.      } else {
  1468.         lv  = data;
  1469.         min = lv->lv_VisibleEntries;
  1470.         max = lv->lv_ListEntries;
  1471.         num = get_prop_pos(max, min, ((struct PropInfo *)
  1472.                         gad->SpecialInfo)->VertPot);
  1473.         if ((min = lv->lv_TopEntry) != num) {
  1474.            struct Node  *node = lv->lv_TopNode;
  1475.            USHORT i;
  1476.  
  1477.            if (min > num) {
  1478.           for (i = min - num; i > 0; i--) {
  1479.              node = node->ln_Pred;
  1480.           }
  1481.            } else {
  1482.           for (i = num - min; i > 0; i--) {
  1483.              node = node->ln_Succ;
  1484.           }
  1485.            }
  1486.            lv->lv_TopNode  = node;
  1487.            lv->lv_TopEntry = num;
  1488.            if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  1489.           print_list_view_text(egad);
  1490.            }
  1491.         }
  1492.      }
  1493.      real_imsg = NULL;
  1494.      break;
  1495.  
  1496.       case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
  1497.      if (class != GADGETUP) {
  1498.         lv  = data;
  1499.         num = lv->lv_TopEntry;
  1500.         if (num > 0) {
  1501.            lv->lv_TopNode  = lv->lv_TopNode->ln_Pred;
  1502.            lv->lv_TopEntry = value = num - 1;
  1503.            change_gadget(real_egad);
  1504.         }
  1505.      }
  1506.      real_imsg = NULL;
  1507.      break;
  1508.  
  1509.       case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
  1510.      if (class != GADGETUP) {
  1511.         lv  = data;
  1512.         min = lv->lv_VisibleEntries;
  1513.         max = lv->lv_ListEntries;
  1514.         num = lv->lv_TopEntry + 1;
  1515.         if (num < max && (max - num) >= min) {
  1516.            lv->lv_TopNode  = lv->lv_TopNode->ln_Succ;
  1517.            lv->lv_TopEntry = value = num;
  1518.            change_gadget(real_egad);
  1519.         }
  1520.      }
  1521.      real_imsg = NULL;
  1522.      break;
  1523.  
  1524.       case EXTENDED_GADGET_TYPE_LISTVIEW_ENTRY :
  1525.      lv  = data;
  1526.      max = lv->lv_ListEntries;
  1527.      num = lv->lv_TopEntry + egad->eg_Gadget.GadgetID;
  1528.      if (num < max) {
  1529.         lv->lv_SelectedEntry = value = num;
  1530.         if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  1531.            change_gadget(real_egad);
  1532.         }
  1533.      } else {
  1534.         real_imsg = NULL;
  1535.      }
  1536.      break;
  1537.  
  1538.       case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
  1539.      real_imsg = NULL;
  1540.      break;
  1541.  
  1542.       case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
  1543.      pd                 = data;
  1544.      pd->pd_ActiveColor = value = egad->eg_Gadget.GadgetID;
  1545.      change_gadget(real_egad);
  1546.      break;
  1547.    }
  1548.    if (real_imsg) {
  1549.       imsg = create_intui_message(real_imsg, gl, data_entry, value);
  1550.    }
  1551.    return(imsg);
  1552. }
  1553.     /* Perform hotkey gadget action */
  1554.  
  1555.    STATIC struct IntuiMessage *
  1556. perform_hotkey_action(struct ExtendedGadget  *egad,
  1557.                         struct IntuiMessage  *real_imsg)
  1558. {
  1559.    struct IntuiMessage    *imsg = NULL;
  1560.    struct Gadget          *gad = &egad->eg_Gadget;
  1561.    struct GadgetList      *gl = egad->eg_GadgetList;
  1562.    struct Window          *win = gl->gl_Window;
  1563.    struct RastPort        *rp = win->RPort;
  1564.    USHORT data_entry = egad->eg_DataEntry;
  1565.    struct ExtendedGadget  *real_egad = gl->gl_Gadgets[data_entry];
  1566.    struct MXData          *mx;
  1567.    struct SliderData      *sl;
  1568.    struct ScrollerData    *sc;
  1569.    struct CycleData       *cy;
  1570.    struct CountData       *co;
  1571.    struct ListViewData    *lv;
  1572.    struct PaletteData     *pd;
  1573.    VOID  *data = (VOID *)(real_egad + 1);
  1574.    ULONG min, max, num, flags = real_egad->eg_DataFlags, value = 0,
  1575.      qualifier = real_imsg->Qualifier & QUALIFIER_SHIFT;
  1576.  
  1577.    switch (egad->eg_Type) {
  1578.       case EXTENDED_GADGET_TYPE_BUTTON :
  1579.      if (flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) {
  1580.         if (gad->Flags & SELECTED) {
  1581.  
  1582.            /* Prepare gadget state manually (selected) */
  1583.            change_gadget(real_egad);
  1584.            gad->Flags &= ~SELECTED;
  1585.         } else {
  1586.            gad->Flags |= SELECTED;
  1587.            value       = 1;
  1588.         }
  1589.      } else {
  1590.         if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  1591.            gad->Flags |= SELECTED;
  1592.            change_gadget(real_egad);
  1593.            timer_delay(0L, 100000L);
  1594.  
  1595.            /* Prepare gadget state manually (unselected) */
  1596.            change_gadget(real_egad);
  1597.            gad->Flags &= ~SELECTED;
  1598.         }
  1599.      }
  1600.      change_gadget(real_egad);
  1601.      break;
  1602.  
  1603.       case EXTENDED_GADGET_TYPE_CHECK :
  1604.      if (gad->Flags & SELECTED) {
  1605.         gad->Flags &= ~SELECTED;
  1606.      } else {
  1607.         gad->Flags |= SELECTED;
  1608.         value       = 1;
  1609.      }
  1610.      change_gadget(real_egad);
  1611.      break;
  1612.  
  1613.       case EXTENDED_GADGET_TYPE_MX :
  1614.      mx  = data;
  1615.      max = mx->mx_TextEntries;
  1616.      num = mx->mx_ActiveEntry;
  1617.      if (qualifier) {
  1618.         if (num > 0) {
  1619.            num--;
  1620.         } else {
  1621.            num = max - 1;
  1622.         }
  1623.      } else {
  1624.         if (num < (max - 1)) {
  1625.            num++;
  1626.         } else {
  1627.            num = 0;
  1628.         }
  1629.      }
  1630.      mx->mx_ActiveEntry = value = num;
  1631.      change_gadget(real_egad);
  1632.      break;
  1633.  
  1634.       case EXTENDED_GADGET_TYPE_STRING :
  1635.       case EXTENDED_GADGET_TYPE_INTEGER :
  1636.      activate_input_gadget(gl, data_entry);
  1637.      real_imsg = NULL;
  1638.      break;
  1639.  
  1640.       case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  1641.      sl  = data;
  1642.      min = sl->sl_Min;
  1643.      max = sl->sl_Max;
  1644.      num = sl->sl_Level;
  1645.      if (qualifier) {
  1646.         if ((LONG)num > (LONG)min) {
  1647.            num--;
  1648.         } else {
  1649.            real_imsg = NULL;
  1650.         }
  1651.      } else {
  1652.         if ((LONG)num < (LONG)max) {
  1653.            num++;
  1654.         } else {
  1655.            real_imsg = NULL;
  1656.         }
  1657.      }
  1658.      if (real_imsg) {
  1659.         sl->sl_Level = value = num;
  1660.         change_gadget(real_egad);
  1661.      }
  1662.      break;
  1663.  
  1664.       case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  1665.      sc  = data;
  1666.      min = sc->sc_Visible;
  1667.      max = sc->sc_Total;
  1668.      num = sc->sc_Top;
  1669.      if (qualifier) {
  1670.         if (num > 0) {
  1671.            num--;
  1672.         } else {
  1673.            real_imsg = NULL;
  1674.         }
  1675.      } else {
  1676.         if (num < (max - min)) {
  1677.            num++;
  1678.         } else {
  1679.            real_imsg = NULL;
  1680.         }
  1681.      }
  1682.      if (real_imsg) {
  1683.         sc->sc_Top = value = num;
  1684.         change_gadget(real_egad);
  1685.      }
  1686.      break;
  1687.  
  1688.       case EXTENDED_GADGET_TYPE_CYCLE :
  1689.      cy  = data;
  1690.      max = cy->cy_TextEntries;
  1691.      num = cy->cy_ActiveEntry;
  1692.      if (qualifier) {
  1693.         if (num > 0) {
  1694.            num--;
  1695.         } else {
  1696.            num = max - 1;
  1697.         }
  1698.      } else {
  1699.         if (num < (max - 1)) {
  1700.            num++;
  1701.         } else {
  1702.            num = 0;
  1703.         }
  1704.      }
  1705.      if (cy->cy_ActiveEntry != num) {
  1706.         cy->cy_ActiveEntry = value = num;
  1707.         change_gadget(real_egad);
  1708.      } else {
  1709.         real_imsg = NULL;
  1710.      }
  1711.      break;
  1712.  
  1713.       case EXTENDED_GADGET_TYPE_COUNT :
  1714.      co  = data;
  1715.      min = co->co_Min;
  1716.      max = co->co_Max;
  1717.      num = co->co_Value;
  1718.      if (qualifier) {
  1719.         if ((LONG)num > (LONG)min) {
  1720.            num--;
  1721.         } else {
  1722.            real_imsg = NULL;
  1723.         }
  1724.      } else {
  1725.         if ((LONG)num < (LONG)max) {
  1726.            num++;
  1727.         } else {
  1728.            real_imsg = NULL;
  1729.         }
  1730.      }
  1731.      if (real_imsg) {
  1732.         co->co_Value = value = num;
  1733.         change_gadget(real_egad);
  1734.      }
  1735.      break;
  1736.  
  1737.       case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  1738.      lv  = data;
  1739.      min = lv->lv_VisibleEntries;
  1740.      max = lv->lv_ListEntries;
  1741.      if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  1742.         num = lv->lv_SelectedEntry;
  1743.      } else {
  1744.         num = lv->lv_TopEntry;
  1745.      }
  1746.      if (qualifier) {
  1747.         if (num > 0) {
  1748.            num--;
  1749.         } else {
  1750.            real_imsg = NULL;
  1751.         }
  1752.      } else {
  1753.         if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  1754.            if (++num >= max) {
  1755.           real_imsg = NULL;
  1756.            }
  1757.         } else {
  1758.            if (++num >= max || (max - num) < min) {
  1759.           real_imsg = NULL;
  1760.            }
  1761.         }
  1762.      }
  1763.      if (real_imsg) {
  1764.         set_gadget_attributes(gl, data_entry, 0L, 0L, USE_CURRENT_VALUE,
  1765.                         num, (VOID *)USE_CURRENT_VALUE);
  1766.         if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  1767.            value = lv->lv_SelectedEntry;
  1768.         } else {
  1769.            real_imsg = NULL;
  1770.         }
  1771.      }
  1772.      break;
  1773.  
  1774.       case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
  1775.       case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
  1776.      pd  = data;
  1777.      min = pd->pd_ColorOffset;
  1778.      max = pd->pd_MaxColors;
  1779.      num = pd->pd_ActiveColor;
  1780.      if (qualifier) {
  1781.         if ((LONG)num > (LONG)min) {
  1782.            num--;
  1783.         } else {
  1784.            num = min + max - 1;
  1785.         }
  1786.      } else {
  1787.         if ((LONG)num < (LONG)(min + max - 1)) {
  1788.            num++;
  1789.         } else {
  1790.            num = min;
  1791.         }
  1792.      }
  1793.      pd->pd_ActiveColor = value = num;
  1794.      change_gadget(real_egad);
  1795.      break;
  1796.    }
  1797.    if (real_imsg) {
  1798.       imsg = create_intui_message(real_imsg, gl, data_entry, value);
  1799.    }
  1800.    return(imsg);
  1801. }
  1802.     /* Create special ISUP intui message */
  1803.  
  1804.    STATIC struct IntuiMessage *
  1805. create_intui_message(struct IntuiMessage  *real_imsg, struct GadgetList  *gl,
  1806.                          USHORT data_entry,    ULONG value)
  1807. {
  1808.    struct IntuiMessage  *imsg = NULL;
  1809.  
  1810.    if (!(imsg = AllocMem((LONG)(sizeof(struct IntuiMessage) +
  1811.                 sizeof(struct IntuiMessage *)), MEMF_PUBLIC))) {
  1812.       imsg = real_imsg;
  1813.    } else {
  1814.  
  1815.       /* Init ISUP intui message */
  1816.       CopyMem((BYTE *)real_imsg, (BYTE *)imsg, sizeof(struct IntuiMessage));
  1817.       imsg->Class       = ISUP_ID;
  1818.       imsg->Code        = data_entry;
  1819.       imsg->IAddress    = (APTR)value;
  1820.       imsg->SpecialLink = (struct IntuiMessage *)gl;
  1821.  
  1822.       /* Put real IntuiMessage ptr direct after ISUP intuition message */
  1823.       *(struct IntuiMessage **)(imsg + 1) = real_imsg;
  1824.    }
  1825.    return(imsg);
  1826. }
  1827.     /* Get active gadget for given window */
  1828.  
  1829.    STATIC struct ExtendedGadget *
  1830. get_active_gadget(struct Window  *win)
  1831. {
  1832.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1833.    struct ExtendedGadget      *egad = NULL;
  1834.    USHORT count;
  1835.  
  1836.    ObtainSemaphore(&vg->vg_Semaphore);
  1837.    if (count = vg->vg_Count) {
  1838.       struct GadgetList  *gl = (struct GadgetList *)vg->vg_MinList.mlh_Head;
  1839.       USHORT i;
  1840.  
  1841.       for (i = 0; i < count; i++) {
  1842.      if (gl->gl_Window == win && gl->gl_ActiveGadget) {
  1843.         egad = gl->gl_ActiveGadget;
  1844.         break;
  1845.  
  1846.      }
  1847.      gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
  1848.       }
  1849.    }
  1850.    ReleaseSemaphore(&vg->vg_Semaphore);
  1851.    return(egad);
  1852. }
  1853.     /* Get hotkey gadget for given window */
  1854.  
  1855.    STATIC struct ExtendedGadget *
  1856. get_hotkey_gadget(struct Window  *win, USHORT hotkey)
  1857. {
  1858.    struct ExtendedGadget  *result_egad = NULL;
  1859.  
  1860.    /* First check for valid hotkey (printable character) */
  1861.    hotkey = tolower(hotkey);
  1862.    if (hotkey >= ' ' && hotkey <= '~') {
  1863.       struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1864.       USHORT count;
  1865.  
  1866.       /* Now check if any visible gadget list exists */
  1867.       ObtainSemaphore(&vg->vg_Semaphore);
  1868.       if (count = vg->vg_Count) {
  1869.      struct GadgetList  *gl = (struct GadgetList *)
  1870.                             vg->vg_MinList.mlh_Head;
  1871.      USHORT i;
  1872.      BOOL   found = FALSE;
  1873.  
  1874.      /* Search all gadget lists displayed on given window */
  1875.      for (i = 0; i < count && found == FALSE; i++) {
  1876.         if (gl->gl_Window == win) {
  1877.            USHORT j, data_entries = gl->gl_DataEntries;
  1878.  
  1879.            /* Search gadget with given hotkey */
  1880.            for (j = 0; j < data_entries && found == FALSE; j++) {
  1881.           struct ExtendedGadget  *egad = gl->gl_Gadgets[j];
  1882.  
  1883.           if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOTKEY &&
  1884.                         egad->eg_Hotkey == hotkey) {
  1885.              result_egad = egad;
  1886.              found       = TRUE;
  1887.           }
  1888.            }
  1889.         }
  1890.         gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
  1891.      }
  1892.       }
  1893.       ReleaseSemaphore(&vg->vg_Semaphore);
  1894.    }
  1895.    return(result_egad);
  1896. }
  1897.     /* Remove visible gadget lists from given window */
  1898.  
  1899.    USHORT
  1900. remove_visible_gadget_lists(struct Window  *win, struct MinList  *list)
  1901. {
  1902.    struct GadgetList  *gl;
  1903.    USHORT count = 0;
  1904.  
  1905.    NewList((struct List *)list);
  1906.    while (gl = get_first_gadget_list(win)) {
  1907.       remove_gadgets(gl);
  1908.       AddHead((struct List *)list, (struct Node *)&gl->gl_MinNode);
  1909.       count++;
  1910.    }
  1911.    return(count);
  1912. }
  1913.     /* Find first visible gadget list for given window */
  1914.  
  1915.    STATIC struct GadgetList  *
  1916. get_first_gadget_list(struct Window  *win)
  1917. {
  1918.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1919.    struct GadgetList          *gl, *gl_return = NULL;
  1920.  
  1921.    ObtainSemaphore(&vg->vg_Semaphore);
  1922.    gl = (struct GadgetList *)&vg->vg_MinList.mlh_Head;
  1923.    while (gl->gl_MinNode.mln_Succ) {
  1924.       if (gl->gl_Window == win) {
  1925.      gl_return = gl;
  1926.      break;
  1927.       }
  1928.       gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
  1929.    }
  1930.    ReleaseSemaphore(&vg->vg_Semaphore);
  1931.    return(gl_return);
  1932. }
  1933.     /* Display visible gadget lists on given window */
  1934.  
  1935.    VOID
  1936. display_visible_gadget_lists(struct Window  *win, struct MinList  *list)
  1937. {
  1938.    struct GadgetList  *gl;
  1939.  
  1940.    while (gl = (struct GadgetList *)RemHead((struct List *)list)) {
  1941.       display_gadgets(win, gl);
  1942.    }
  1943. }
  1944.     /* Convert given RAWKEY IntuiMessage to ASCII */
  1945.  
  1946.    UBYTE
  1947. convert_rawkey_to_ascii(struct IntuiMessage  *im)
  1948. {
  1949.    UBYTE key = 0;
  1950.  
  1951.    /* First check for RAWKEY event */
  1952.    if (im->Class == RAWKEY) {
  1953.       struct InputEvent  input_event, *ie = &input_event;
  1954.       BYTE buffer[CONVERT_BUFFER_SIZE];
  1955.  
  1956.       /* Build InputEvent for console device */
  1957.       ie->ie_NextEvent    = NULL;
  1958.       ie->ie_Class        = IECLASS_RAWKEY;
  1959.       ie->ie_SubClass     = IECLASS_NULL;
  1960.       ie->ie_Code         = im->Code;
  1961.       ie->ie_Qualifier    = im->Qualifier;
  1962.       ie->ie_EventAddress = *((APTR *)im->IAddress);
  1963.  
  1964.       /* Convert it and check number of returned keys */
  1965.       if (RawKeyConvert(ie, &buffer[0], CONVERT_BUFFER_SIZE, NULL) == 1) {
  1966.      key = (UBYTE)buffer[0];
  1967.       }
  1968.    }
  1969.    return(key);
  1970. }
  1971.